#include "../mars/thread.h"
#include <stdio.h>
#include <stdlib.h>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>

void run() {
    for (;;) {
        sleep(1);
        printf("tid: %d, name: %s, main_thread: %d\n", 
                mars::CurrentThread::tid(),
                mars::CurrentThread::name(),
                mars::CurrentThread::is_main_thread());
    }
}

void run_with_arg(int x) {
    for (;;) {
        sleep(1);
        printf("tid: %d, name: %s, main_thread: %d, x: %d\n", 
                mars::CurrentThread::tid(),
                mars::CurrentThread::name(),
                mars::CurrentThread::is_main_thread(),
                x);
    }
}

void run_in_main() {
    int i = 10;
    while(i--) {
        sleep(1);
        printf("tid: %d, name: %s, main_thread: %d\n", 
                mars::CurrentThread::tid(),
                mars::CurrentThread::name(),
                mars::CurrentThread::is_main_thread());
    }
}

class Person {
    public:
        Person(const std::string& name, int age): _name(name), _age(age) {}
        ~Person() { printf("Person destroy\n"); };
        void show() {
            for(;;) {
                sleep(1);
                printf("name: %s, age: %d\n", _name.c_str(), _age);
            }
        }

    private:
        std::string _name;
        int _age;
};

int main() {
    {
        boost::shared_ptr<Person> p(new Person("zoro", 21));
        mars::Thread t1(run, "allen");
        mars::Thread t2(run, "luffy");
        mars::Thread t3(boost::bind(run_with_arg, 10), "nami");
        mars::Thread t4(boost::bind(run_with_arg, 11), "sanji");
        mars::Thread t5(boost::bind(&Person::show, p), "zoro");

        printf("tid: %d, name: %s, main_thread: %d\n", 
                mars::CurrentThread::tid(),
                mars::CurrentThread::name(),
                mars::CurrentThread::is_main_thread());

        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }

    run_in_main();

    printf("finished\n");
    return 0;
}
